package org.changs.nav.delegate.global;

/**
 * Created by yincs on 2017/8/29.
 */

import android.content.Context;
import android.text.TextUtils;
import android.widget.Toast;

import com.amap.api.location.AMapLocation;
import com.amap.api.location.AMapLocationClient;
import com.amap.api.location.AMapLocationClientOption;
import com.amap.api.location.AMapLocationListener;

import org.changs.nav.delegate.amap.domain.SimpleLocation;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;

import javax.inject.Inject;
import javax.inject.Singleton;

import timber.log.Timber;

/**
 * 定位、获取自己当前位置、gps定位、网络定位、检测是否开启gps定位
 */

@Singleton
public class AmapLocationTask {

    private AMapLocationClient locationClient = null;
    private AMapLocationClientOption locationOption = null;
    private List<OnLocationListener> mListeners;
    private AMapLocation mAMapLocation;
    private SimpleLocation mSimpleLocation;
    private final Context mContext;

    @Inject
    public AmapLocationTask(Context context) {
        mContext = context;
        Timber.d("context = " + context + " :::  " + hashCode());
        locationClient = new AMapLocationClient(context);
        locationOption = getDefaultOption();
        //设置定位参数
        locationClient.setLocationOption(locationOption);
        // 设置定位监听
        locationClient.setLocationListener(locationListener);
    }

    //113.924929,22.553405
    private AMapLocationClientOption getDefaultOption() {
        AMapLocationClientOption mOption = new AMapLocationClientOption();
        mOption.setLocationMode(AMapLocationClientOption.AMapLocationMode.Hight_Accuracy);//可选，设置定位模式，可选的模式有高精度、仅设备、仅网络。默认为高精度模式
        mOption.setGpsFirst(false);//可选，设置是否gps优先，只在高精度模式下有效。默认关闭
        mOption.setHttpTimeOut(30000);//可选，设置网络请求超时时间。默认为30秒。在仅设备模式下无效
        mOption.setInterval(2000);//可选，设置定位间隔。默认为2秒
        mOption.setNeedAddress(true);//可选，设置是否返回逆地理地址信息。默认是true
        mOption.setOnceLocation(false);//可选，设置是否单次定位。默认是false
        mOption.setOnceLocationLatest(false);//可选，设置是否等待wifi刷新，默认为false.如果设置为true,会自动变为单次定位，持续定位时不要使用
        AMapLocationClientOption.setLocationProtocol(AMapLocationClientOption.AMapLocationProtocol.HTTP);//可选， 设置网络请求的协议。可选HTTP或者HTTPS。默认为HTTP
        mOption.setSensorEnable(true);//可选，设置是否使用传感器。默认是false
        mOption.setWifiScan(true); //可选，设置是否开启wifi扫描。默认为true，如果设置为false会同时停止主动刷新，停止以后完全依赖于系统刷新，定位位置可能存在误差
        mOption.setLocationCacheEnable(true); //可选，设置是否使用缓存定位，默认为true
        return mOption;
    }

    public AMapLocation getLastKnownLocation() {
        if (mAMapLocation == null)
            mAMapLocation = locationClient.getLastKnownLocation();
        if (mAMapLocation == null || mAMapLocation.getErrorCode() != 0) {
            mAMapLocation = new AMapLocation("");
            Timber.d("getLastKnownLocation: 定位失败,使用模拟位置");
            mAMapLocation.setLongitude(114.047175);
            mAMapLocation.setLatitude(22.559202);
        }
        return mAMapLocation;
    }

    public void registerListener(OnLocationListener listener) {
        if (mListeners == null) mListeners = new ArrayList<>();
        mListeners.add(listener);
    }

    public void unregisterListener(OnLocationListener listener) {
        if (mListeners == null) return;
        mListeners.remove(listener);
    }

    public void startLocation() {
        // 设置定位参数
        locationClient.setLocationOption(locationOption);
        // 启动定位
        locationClient.startLocation();
    }

    public void stopLocation() {
        // 停止定位
        locationClient.stopLocation();
    }


    public SimpleLocation getLocation() {
        return mSimpleLocation;
    }

    /**
     * 如果AMapLocationClient是在当前Activity实例化的，
     * 在Activity的onDestroy中一定要执行AMapLocationClient的onDestroy
     */
    public void destroyLocation() {
        if (null != locationClient) {
            locationClient.onDestroy();
            locationClient = null;
            locationOption = null;
        }
    }

    /**
     * 定位监听
     */
    private AMapLocationListener locationListener = new AMapLocationListener() {
        @Override
        public void onLocationChanged(AMapLocation location) {
            if (null != location) {
                StringBuffer sb = new StringBuffer();
                //errCode等于0代表定位成功，其他的为定位失败，具体的可以参照官网定位错误码说明
                if (location.getErrorCode() == 0) {
                    mAMapLocation = location;
                    sb.append("定位成功" + "\n");
                    sb.append("定位类型: " + location.getLocationType() + "\n");
                    sb.append("经    度    : " + location.getLongitude() + "\n");
                    sb.append("纬    度    : " + location.getLatitude() + "\n");
                    sb.append("精    度    : " + location.getAccuracy() + "米" + "\n");
                    sb.append("提供者    : " + location.getProvider() + "\n");

                    sb.append("速    度    : " + location.getSpeed() + "米/秒" + "\n");
                    sb.append("角    度    : " + location.getBearing() + "\n");
                    // 获取当前提供定位服务的卫星个数
                    sb.append("星    数    : " + location.getSatellites() + "\n");
                    sb.append("国    家    : " + location.getCountry() + "\n");
                    sb.append("省            : " + location.getProvince() + "\n");
                    sb.append("市            : " + location.getCity() + "\n");
                    sb.append("城市编码 : " + location.getCityCode() + "\n");
                    sb.append("区            : " + location.getDistrict() + "\n");
                    sb.append("区域 码   : " + location.getAdCode() + "\n");
                    sb.append("地    址    : " + location.getAddress() + "\n");
                    sb.append("兴趣点    : " + location.getPoiName() + "\n");
                    //定位完成的时间
                    sb.append("定位时间: " + formatUTC(location.getTime(), "yyyy-MM-dd HH:mm:ss") + "\n");
                } else {
                    //定位失败
                    sb.append("定位失败" + "\n");
                    sb.append("错误码:" + location.getErrorCode() + "\n");
                    sb.append("错误信息:" + location.getErrorInfo() + "\n");
                    sb.append("错误描述:" + location.getLocationDetail() + "\n");
                }
                //定位之后的回调时间
                sb.append("回调时间: " + formatUTC(System.currentTimeMillis(), "yyyy-MM-dd HH:mm:ss") + "\n");

                //解析定位结果，
                String result = sb.toString();
                Timber.d("定位结果成功: " + result);
                if (location.getErrorCode() != 0) {
                    Toast.makeText(mContext, result, Toast.LENGTH_SHORT).show();
                }
            } else {
                Timber.e("定位失败，loc is null");
            }

            int code;
            String msg;
            SimpleLocation simpleLocation = null;
            if (location == null) {
                code = 999999;
                msg = "定位失败";
            } else if (location.getErrorCode() != 0) {
                code = location.getErrorCode();
                msg = location.getErrorInfo();
            } else {
                code = 0;
                msg = "success";
                simpleLocation = SimpleLocation.fromAmapLocation(location);
            }

            if (simpleLocation != null) {
                mSimpleLocation = simpleLocation;
            }
            if (mListeners != null) {
                for (OnLocationListener listener : mListeners) {
                    listener.onLocationChanged(code, msg, simpleLocation);
                }
            }
        }
    };

    private static SimpleDateFormat sdf = null;

    public static String formatUTC(long l, String strPattern) {
        if (TextUtils.isEmpty(strPattern)) {
            strPattern = "yyyy-MM-dd HH:mm:ss";
        }
        if (sdf == null) {
            try {
                sdf = new SimpleDateFormat(strPattern, Locale.CHINA);
            } catch (Throwable e) {
            }
        } else {
            sdf.applyPattern(strPattern);
        }
        return sdf == null ? "NULL" : sdf.format(l);
    }


    public interface OnLocationListener {
        void onLocationChanged(int code, String msg, SimpleLocation location);
    }
}
